package com.cooqe.collection_snmp.snmpfinder;

import com.alibaba.fastjson.JSONObject;
import com.cooqe.collection_snmp.model.SnmpParameter;
import com.cooqe.collection_snmp.utils.SnmpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.snmp4j.PDU;
import org.snmp4j.ScopedPDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.VariableBinding;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
 * @author 折戟沉沙铁未销
 * @version V1.0
 * @date 2023/11/14-2023
 * @Description: snmp get 方式进行指标的采集
 */
@Component
@Slf4j
@SuppressWarnings("all")
public class SnmpGetHandle {

    /**
     * snmp get 操作，进行oid 指标值的获取
     * ----------------------------------------
     * {
     * "method": "get",
     * "oids": "1.2.3.2.6,1.2.3.2.6"
     * }
     * ----------------------------------------
     * {
     * "method": "get",
     * "oids": "1.2.3.2.6:1.2.3.2.7"
     * }
     * ----------------------------------------
     */
    public Map<String, List<String>> snmpGet(JSONObject collectParamsObj, SnmpParameter snmpParameter, Target target, Snmp snmp) throws Exception {
        //获取参数 oid
        String oids = collectParamsObj.getString(SnmpUtil.OIDS);
        String[] oidArrays = oids.split(SnmpUtil.REGEX_SEGMENT);

        //定义解析结果
        Map<String, List<String>> resultMap = new HashMap<>();

        //遍历oid，查询对应的指标值
        for (String oidVal : oidArrays) {

            /**
             * xxx:zzz 这种拼接的形式，就是为了尽最大尝试而使用的。并不是对拼接的所有oid都进行一次采集请求。
             * xxx:zzz  对于这种, 一个 oid字符串中使用 : 进行拼接的多个OID。
             * 在采集的时候，首先进行分割。 依次使用得到的单个 OID 进行 get 一些列操作。
             * 当第一个OID出现首次 get 出现错误的时候。此时会 continue, 使用 : 后的 OID 再进行该指标的采集。
             * 如果 xxx:zzz 使用xxx 就已经取回了采集的数据，不会再使用 zzz 进行采集了。
             */
            String[] arrayOids = oidVal.split(SnmpUtil.REGEX_TEXT);
            for (int i = 0; i < arrayOids.length; i++) {
                //定义参数
                String requestOid = arrayOids[i];
                PDU pdu = (snmpParameter.getVersion() == SnmpConstants.version3) ? (new ScopedPDU()) : (new PDU());
                pdu.add(new VariableBinding(new OID(requestOid)));
                pdu.setType(snmpParameter.getMethodType());  //PDU.GET、 PDU.GETNEXT

                //发送请求
                ResponseEvent responseEvent = snmp.send(pdu, target);
                if (responseEvent == null) {
                    log.error("responseEvent is null error");
                    continue;
                }
                if (responseEvent.getResponse() == null) {
                    log.error("responseEvent is null error");
                    continue;
                }
                if (responseEvent.getError() != null) {
                    log.error(responseEvent.getError().getMessage());
                    continue;
                }
                if (responseEvent.getResponse().getErrorStatus() != PDU.noError) {
                    log.error("responseEvent.getResponse().getErrorStatus() is error");
                    continue;
                }

                //获取返回结果
                //map结果是 {1.2.1.3.14.5.6: : [23]}   或者  map结果是 {1.2.1.3.14.5.6:1.2.1.3.14.5.6 : [23,59]} 这样的
                Vector<? extends VariableBinding> variableBindings = responseEvent.getResponse().getVariableBindings();
                SnmpUtil.resolveSnmpReturnValue(resultMap, pdu.getType(), variableBindings, requestOid, oidVal);

                //将结果为空的进行删除
                List<String> oidListValuesList = resultMap.get(oidVal);
                if (oidListValuesList != null) {
                    oidListValuesList.removeIf(StringUtils::isBlank);
                }
                break;
            }
        }
        //返回
        return resultMap;
    }
}